package com.alpha.eceasy.mall.service.impl;

import cn.hutool.core.util.StrUtil;
import com.alpha.eceasy.extension.BaseFormInfo;
import com.alpha.eceasy.mall.api.vo.MallOrderDetailBidVO;
import com.alpha.eceasy.mall.util.SecurityUtils;
import com.alpha.eceasy.exception.BizException;
import com.alpha.eceasy.extension.BaseServiceImpl;
import com.alpha.eceasy.mall.api.dto.MallOrderDTO;
import com.alpha.eceasy.mall.api.entity.*;
import com.alpha.eceasy.mall.api.vo.MallOrderDetailVO;
import com.alpha.eceasy.mall.api.vo.MallOrderVO;
import com.alpha.eceasy.mall.mapper.MallOrderMapper;
import com.alpha.eceasy.mall.service.*;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;
import java.util.Objects;
import java.util.Optional;
import java.util.stream.Collectors;

/**
 * 订单接口
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class MallOrderServiceImpl extends BaseServiceImpl<MallOrderMapper, MallOrder> implements MallOrderService {
    private final MallCommoditySpecificationServiceImpl commoditySpecificationService;
    private final MallOrderDetailServiceImpl mallOrderDetailService;
    private final MallCommodityDetailServiceImpl mallCommodityDetailService;
    private final MallCommodityServiceImpl mallCommodityService;
    private final MallCustomerServiceImpl mallCustomerService;
    private final MallOrderDetailBidServiceImpl orderDetailBidService;


    @Override
    public MallOrderVO getByGuidVO(String orderGuid) {
        MallOrderVO orderVO = new MallOrderVO();
        BeanUtils.copyProperties(this.getByGuid(orderGuid), orderVO);
        //获取订单详情列表
        List<MallOrderDetail> detailVOList = mallOrderDetailService
                .list(new LambdaQueryWrapper<MallOrderDetail>()
                        .eq(MallOrderDetail::getOrderGuid, orderGuid))
                .stream()
                .map(this::getMallOrderDetailVO)
                .collect(Collectors.toList());
        orderVO.setDetailVOList(detailVOList.stream()
                .map(this::getMallOrderDetailVO)
                .toList());
        //获取用户信息
        SecurityUtils.getRoles()
                .stream()
                .map(role -> switch (role) {
                    case "USER" -> SecurityUtils.getUserInfo();
                    case "INNER" -> mallCustomerService.getByGuid(orderVO.getCustomerGuid());
                    default -> new MallCustomer();
                })
                .findFirst()
                .ifPresent(customer -> orderVO.setCustomerPhone(customer.getTelephone()));
        return orderVO;
    }

    @Override
    public IPage<MallOrderVO> pageOrderVO(Page<MallOrder> page, MallOrderDTO order) {
        LambdaQueryWrapper<MallOrder> wrapper = Wrappers.<MallOrder>lambdaQuery()
                .eq(StrUtil.isNotBlank(order.getGuid()),
                        MallOrder::getGuid, order.getGuid())
                .eq(StrUtil.isNotBlank(order.getCustomerName()),
                        MallOrder::getCustomerGuid, Optional.ofNullable(mallCustomerService.getByCustomerName(order.getCustomerName())).map(MallCustomer::getGuid).orElse("=="))
                .le(Objects.nonNull(order.getOrderType()),
                        BaseFormInfo::getState, 1)
                .orderByDesc(MallOrder::getCreateTime);
        if (StrUtil.isNotBlank(order.getOffererGuid())) {
            List<String> orderDetailGuidList = orderDetailBidService.getOrderDetailBidList(order.getOffererGuid()).stream().map(MallOrderDetailBid::getOrderDetailGuid).toList();
            List<String> orderGuidList = mallOrderDetailService.list(Wrappers.<MallOrderDetail>lambdaQuery()
                            .in(CollectionUtils.isNotEmpty(orderDetailGuidList), BaseFormInfo::getGuid, orderDetailGuidList))
                    .stream().map(MallOrderDetail::getOrderGuid).distinct().toList();
            wrapper.in(CollectionUtils.isNotEmpty(orderGuidList),
                            MallOrder::getGuid, orderGuidList)
                    .eq(CollectionUtils.isEmpty(orderGuidList),
                            MallOrder::getGuid, "===");
        } else {
            SecurityUtils.getRoles().forEach(role -> {
                        switch (role) {
                            case "INNER" -> {
                                if (StrUtil.isNotBlank(order.getSellerGuid())) {
                                    List<String> customerGuidList = mallCustomerService.list(Wrappers.<MallCustomer>lambdaQuery()
                                                    .eq(MallCustomer::getSellerGuid, order.getSellerGuid()))
                                            .stream().map(MallCustomer::getGuid).toList();
                                    wrapper.in(MallOrder::getCustomerGuid, customerGuidList.isEmpty() ? List.of("") : customerGuidList);
                                }
                            }
                            case "USER" -> wrapper.eq(MallOrder::getCustomerGuid, SecurityUtils.getUserGuid());
                        }
                    }
            );
        }
        return this.page(page, wrapper).convert(this::getOrderVO);
    }


    /**
     * 将MallOrderDetail转化为MallOrderDetailVO
     */
    private MallOrderDetailVO getMallOrderDetailVO(MallOrderDetail item) {
        MallOrderDetailVO vo = new MallOrderDetailVO();
        BeanUtils.copyProperties(item, vo);
        String specificationGuid = item.getCommoditySpecificationGuid();
        MallCommoditySpecification specification = commoditySpecificationService.getByGuid(specificationGuid);
        vo.setSpecificationName(specification.getSpecificationName());
        vo.setSpecificationCoverList(specification.getSpecificationCoverList());
        vo.setSpecificationPrice(specification.getSellPrice());
        vo.setSpecificationSku(specification.getSku());
        Optional.ofNullable(mallCommodityService.getByGuid(specification.getCommodityGuid()))
                .ifPresent(commodity -> {
                    vo.setCommodityGuid(commodity.getGuid());
                    vo.setCommodityIcon(commodity.getIcon());
                    vo.setCommodityName(commodity.getCommodityName());
                });
        return vo;
    }

    /**
     * 将订单包装成vo
     *
     * @param order 支付订单
     * @return MallOrderVO
     */
    private MallOrderVO getOrderVO(MallOrder order) {
        MallOrderVO vo = new MallOrderVO();
        BeanUtils.copyProperties(order, vo);
        List<MallOrderDetail> mallOrderDetailList = mallOrderDetailService.list(Wrappers.<MallOrderDetail>lambdaQuery()
                .eq(MallOrderDetail::getOrderGuid, order.getGuid()));
        if (CollectionUtils.isNotEmpty(mallOrderDetailList)) {
            vo.setDetailVOList(mallOrderDetailList.stream().map(this::getMallOrderDetailVO).toList());
        }
        Optional.ofNullable(mallCustomerService.getByGuid(order.getCustomerGuid()))
                .ifPresent(customer -> {
                    vo.setCustomerName(customer.getName());
                    vo.setCustomerPhone(customer.getTelephone());
                });
        return vo;
    }

    @Transactional(rollbackFor = Exception.class)
    public Boolean saveDTO(MallOrderDTO dto) {
        MallOrder order = new MallOrder(dto);
        if (SecurityUtils.getRoles().contains("USER")) {
            order.setCustomerGuid(SecurityUtils.getUserGuid());
        }
        order.setOrderType(0);
        if (!this.save(order)) {
            throw new BizException("保存失败");
        }
        return dto.getOrderDetailList().stream()
                .peek(orderDetail -> orderDetail.setOrderGuid(order.getGuid()))
                .allMatch(mallOrderDetailService::save);
    }

    public MallOrderVO getDetailVOByGuid(String guid, String offererGuid) {
        MallOrderVO vo = this.getByGuidVO(guid);
        List<MallOrderDetailVO> orderDetailVOList = vo.getDetailVOList().stream()
                .peek(detail -> detail.setOrderDetailBidList(orderDetailBidService.list(Wrappers.<MallOrderDetailBid>lambdaQuery()
                                .eq(MallOrderDetailBid::getOrderDetailGuid, detail.getGuid())
                                .eq(StrUtil.isNotBlank(offererGuid),
                                        MallOrderDetailBid::getOffererGuid, offererGuid))
                        .stream()
                        .map(MallOrderDetailBidVO::new)
                        .toList()))
                .toList();
        vo.setDetailVOList(orderDetailVOList);
        Optional.ofNullable(mallCustomerService.getByGuid(vo.getCustomerGuid()))
                .ifPresent(customer -> {
                    vo.setCustomerName(customer.getName());
                    vo.setCustomerPhone(customer.getTelephone());
                });
        return vo;
    }

    @Transactional(rollbackFor = Exception.class)
    public boolean updateDTOByGuid(MallOrderDTO dto) {
        Optional.ofNullable(dto.getOrderDetailList())
                .ifPresent(list -> list.forEach(mallOrderDetailService::updateByGuid));
        return super.update(Wrappers.<MallOrder>lambdaUpdate()
                .eq(BaseFormInfo::getGuid, dto.getGuid())
                .set(MallOrder::getState, dto.getState()));
    }
}
